# coding = utf-8
"""
Question:
有三个水桶，分别为8L，5L，3L，
现在有8L的水在8L的桶里，怎样倒水可以平分成两份；
桶没有刻度，不可以借助其他工具。

"""


# 水桶的状态模型(8L,3L,5L)中的水量
# initstate = (8, 0, 0)
# finalstate = (4, 0, 4)
# 记录已经处理过的状态,防止死循环
# alreadystate = [initstate]
# 状态迁移的动作记录数据结构使用map和list的复合结构,来表示树形结构
# tree = {initstate: 'null'}
# print(tree)



class Bucket:
    def __init__(self, water: int, size: int):
        self.water = water
        self.size = size


class State:
    def __init__(self, big: Bucket, mid: Bucket, small: Bucket):
        self.state = [big.water, mid.water, small.water]


class BigBucket(Bucket):
    def __init__(self, water: int):
        Bucket.__init__(self, water, 8)


class MidBucket(Bucket):
    def __init__(self, water: int):
        Bucket.__init__(self, water, 5)


class SmallBucket(Bucket):
    def __init__(self, water: int):
        Bucket.__init__(self, water, 3)


# 动作模型
'''
   倒水的动作:从哪到哪倒多少;
    给水桶编号ABC,即放向和三个水桶的全排列,倒水量视情况而定
'''


class Action:
    def __init__(self, fromwhere: Bucket, towhere: Bucket, water):
        self.fromwhere = fromwhere
        self.towhere = towhere
        self.water = water


def doaction(frstate: State, act: Action):
    srcstate = frstate.state.copy()
    modstate = frstate.state.copy()
    if isinstance(act.fromwhere, BigBucket):
        if isinstance(act.towhere, MidBucket):
            act.water = min(big.water, mid.size - mid.water)
            modstate[1] = modstate[1] + act.water
        else:
            act.water = min(big.water, small.size - small.water)
            modstate[2] = modstate[2] + act.water
        modstate[0] = modstate[0] - act.water
    elif isinstance(act.fromwhere, MidBucket):
        if isinstance(act.towhere, BigBucket):
            act.water = min(mid.water, big.size - big.water)
            modstate[0] = modstate[0] + act.water
        else:
            act.water = min(mid.water, small.size - small.water)
            modstate[2] = modstate[2] + act.water
        modstate[1] = modstate[1] - act.water
    else:
        if isinstance(act.towhere, MidBucket):
            act.water = min(small.water, mid.size - mid.water)
            modstate[1] = modstate[1] + act.water
        else:
            act.water = min(small.water, big.size - big.water)
            modstate[0] = modstate[0] + act.water
        modstate[2] = modstate[2] - act.water
    if modstate[0] > 8 or modstate[0] < 0 or \
                    modstate[1] > 5 or modstate[1] < 0 or \
                    modstate[2] > 3 or modstate[2] < 0:
        frstate.state = srcstate
    else:
        frstate.state = modstate
    big.water = frstate.state[0]
    mid.water = frstate.state[1]
    small.water = frstate.state[2]
    return frstate


alreadystate = []
changetree = {}

# all actions
big = BigBucket(8)
mid = MidBucket(0)
small = SmallBucket(0)
actions = [Action(big, mid, min(big.water, mid.size - mid.water)),
           Action(big, small, min(big.water, small.size - small.water)),
           Action(mid, big, min(mid.water, big.size - big.water)),
           Action(mid, small, min(mid.water, small.size - small.water)),
           Action(small, mid, min(small.water, mid.size - mid.water)),
           Action(small, big, min(small.water, big.size - big.water))]


def moveit(fromstate: State):
    tmpstate = fromstate.state.copy()
    alreadystate.append(tmpstate.copy())
    for action in actions:
        # if action.water != 0:
        nextstate = doaction(fromstate, action)
        ac = (action.fromwhere.size, action.towhere.size, action.water)
        # else:
        #     continue
        tns = nextstate.state
        # tmp = nextstate
        print(changetree)
        # tps = tmp.state.copy()
        # print(tps)
        if nextstate.state not in alreadystate:
            moveit(nextstate)
        fromstate.state = tmpstate


if __name__ == '__main__':
    # start move the water
    initstate = State(big=big, mid=mid, small=small)
    moveit(initstate)
